using System;
using System.Collections.Generic;
using System.Text;

namespace GoogleNet
{
    /// <summary>
    /// Link specifies the location of any of the following:
    /// 
    /// <para>
    /// <list type="bullet">
    /// <item>
    /// KML files fetched by network links 
    /// </item>
    /// <item>
    /// Image files used by icons in icon styles, ground overlays, and screen overlays 
    /// </item>
    /// <item>
    /// Model files used in the Model element 
    /// </item>
    /// </list>
    /// </para>
    /// 
    /// <para>
    /// The file is conditionally loaded and refreshed, depending on the refresh parameters supplied here. 
    /// Two different sets of refresh parameters can be specified: one set is based on time (refreshMode and refreshInterval) 
    /// and one is based on the current "camera" view (viewRefreshMode and viewRefreshTime). 
    /// In addition, Link specifies whether to scale the bounding box parameters that are sent to the server 
    /// (viewBoundScale and provides a set of optional viewing parameters that can be sent to the server (viewFormat) 
    /// as well as a set of optional parameters containing version and language information. When a file is fetched, 
    /// the URL that is sent to the server is composed of three pieces of information:
    /// </para>
    /// 
    /// <para>
    /// <list type="bullet">
    /// <item>
    /// the href (Hypertext Reference) that specifies the file to load. 
    /// </item>
    /// <item>
    /// an arbitrary format string that is created from 
    /// (a) parameters that you specify in the viewFormat element or 
    /// (b) bounding box parameters (this is the default and is used if no viewFormat element is included in the file). 
    /// </item>
    /// <item>
    /// a second format string that is specified in the httpQuery element
    /// </item>
    /// </list>
    /// </para>
    /// If the file specified in href is a local file, the viewFormat and httpQuery elements are not used. 
    /// The Link element replaces the Url element of NetworkLink contained in earlier KML releases 
    /// and adds functionality for the Region element (introduced in KML 2.1). 
    /// In Google Earth releases 3.0 and earlier, the Link element is ignored. 
    /// </summary>
    public class KmlLink : IKmlElement
    {
        private string tagName = "Link";

        #region Href
        private Uri href;

        /// <summary>
        /// A URL (either an HTTP address or a local file specification). 
        /// <list type="bullet">
        /// <item>When the parent of Link is a NetworkLink, href is a KML file.</item>
        /// <item>When the parent of Link is a Model, href is a COLLADA file. </item>
        /// <item>When the parent of Link is an Overlay, href is an image. </item>
        /// </list>
        /// Relative URLs can be used in this tag and are evaluated relative to the enclosing KML file. 
        /// </summary>
        /// <value>The href.</value>
        public Uri Href
        {
            get { return href; }
            set { href = value; }
        } 
        #endregion

        #region RefreshMode
        private KmlRefreshModes refreshMode = KmlRefreshModes.onChange;

        /// <summary>
        /// Gets or sets the refresh mode that handles the update of the link associated data.
        /// </summary>
        /// <value>The refresh mode.</value>
        public KmlRefreshModes RefreshMode
        {
            get { return refreshMode; }
            set { refreshMode = value; }
        } 
        #endregion

        #region RefreshInterval
        private int refreshInterval = 4;

        /// <summary>
        /// Gets or sets the refresh interval (in seconds) of the link associated data.
        /// Default = 4 seconds. 
        /// </summary>
        /// <value>The refresh interval.</value>
        public int RefreshInterval
        {
            get { return refreshInterval; }
            set { refreshInterval = value; }
        } 
        #endregion

        #region ViewRefreshMode

        private KmlViewRefreshModes viewRefreshMode = KmlViewRefreshModes.never;

        /// <summary>
        /// Specifies how the link is refreshed when the "camera" changes.
        /// </summary>
        /// <value>The view refresh mode.</value>
        public KmlViewRefreshModes ViewRefreshMode
        {
            get { return viewRefreshMode; }
            set { viewRefreshMode = value; }
        } 
        #endregion

        #region ViewRefreshTime
        private int viewRefreshTime = 4;

        /// <summary>
        /// After camera movement stops, specifies the number of seconds to wait before refreshing the view. 
        /// Default = 4 seconds. (See ViewRefreshMode and its onStop option.) 
        /// </summary>
        /// <value>The view refresh time.</value>
        public int ViewRefreshTime
        {
            get { return viewRefreshTime; }
            set { viewRefreshTime = value; }
        } 
        #endregion

        #region ViewBoundScale
        private double viewBoundScale = 1;

        /// <summary>
        /// Scales the BBOX parameters before sending them to the server. 
        /// Default = 1. A value &lt;1 specifies to use less than the full view (screen). 
        /// A value &gt;1 specifies to fetch an area that extends beyond the edges of the current view. 
        /// </summary>
        /// <value>The view bound scale.</value>
        public double ViewBoundScale
        {
            get { return viewBoundScale; }
            set { viewBoundScale = value; }
        } 
        #endregion

        #region ViewFormat
        private string viewFormat = string.Empty;

        /// <summary>
        /// Specifies the format of the query string that is appended to the Link's href attribute before the file is fetched.
        /// (If the href specifies a local file, this element is ignored.) 
        /// If you specify a ViewRefreshMode of onStop and do not include the viewFormat tag in the file, 
        /// the following information is automatically appended to the query string:
        /// 
        /// <para>
        /// 
        /// BBOX=[bboxWest],[bboxSouth],[bboxEast],[bboxNorth]
        /// 
        /// </para>
        /// 
        /// <para>
        /// 
        /// This information matches the Web Map Service (WMS) bounding box specification.
        /// If you specify an empty viewFormat tag, no information is appended to the query string.
        /// You can also specify a custom set of viewing parameters to add to the query string. 
        /// If you supply a format string, it is used instead of the BBOX information. 
        /// If you also want the BBOX information, you need to add those parameters along with the custom parameters.
        /// 
        /// </para>
        /// 
        /// <para>
        /// You can use any of the following parameters in your format string 
        /// (and Google Earth will substitute the appropriate current value at the time it creates the query string):
        /// <list type="bullet">
        /// <item>[lookatLon], [lookatLat] - longitude and latitude of the point the camera is looking at </item>
        /// <item>[lookatRange], [lookatTilt], [lookatHeading] - camera parameters (see descriptions of range, tilt, and heading in LookAt) </item>
        /// <item>[horizFov], [vertFov] - horizontal, vertical field of view for the camera </item>
        /// <item>[horizPixels], [vertPixels] - size in pixels of the 3D viewer</item>
        /// <item>[terrainEnabled] - indicates whether the 3D viewer is showing terrain </item>
        /// </list>
        /// </para>
        /// 
        /// </summary>
        /// <value>The view format.</value>
        public string ViewFormat
        {
            get { return viewFormat; }
            set { viewFormat = value; }
        } 
        #endregion

        #region HttpQuery
        private string httpQuery = string.Empty;

        /// <summary>
        /// Appends information to the query string, based on the parameters specified. 
        /// (Google Earth substitutes the appropriate current value at the time it 
        /// creates the query string.) 
        /// <para>The following parameters are supported: 
        /// <list type="bullet">
        /// <item>[clientVersion]</item>
        /// <item>[kmlVersion]</item>
        /// <item>[clientName]</item>
        /// <item>[language] </item>
        /// </list>
        /// </para>
        /// </summary>
        /// <value>The HTTP query.</value>
        public string HttpQuery
        {
            get { return httpQuery; }
            set { httpQuery = value; }
        }

        #endregion




        #region IKmlElement Members

        /// <summary>
        /// Name of the KML tag for this specific element.
        /// </summary>
        /// <value></value>
        /// <returns></returns>
        public virtual string TagName
        {
            get { return tagName; }
        }

        #endregion

        #region IKmlGenerator Members

        /// <summary>
        /// Generates the KML for this element including its child elements.
        /// </summary>
        /// <param name="writer">The XML writer that will be used to generate the KML.</param>
        public void GenerateKml(System.Xml.XmlTextWriter writer)
        {
            writer.WriteStartElement(tagName);

            if(href.ToString() != string.Empty)
                writer.WriteElementString("href", href.ToString());

            if (refreshMode != KmlRefreshModes.onChange)
                writer.WriteElementString("refreshMode", refreshMode.ToString());

            if (refreshInterval != 4)
                writer.WriteElementString("refreshInterval", refreshInterval.ToString());

            if (viewRefreshMode != KmlViewRefreshModes.never)
                writer.WriteElementString("viewRefreshMode", viewRefreshMode.ToString());

            if (viewRefreshTime != 4)
                writer.WriteElementString("viewRefreshTime", viewRefreshTime.ToString());

            if (viewBoundScale != 1)
                writer.WriteElementString("viewBoundScale", viewBoundScale.ToString());

            if (viewFormat.ToString() != string.Empty)
                writer.WriteElementString("viewFormat", viewFormat.ToString());

            if (httpQuery.ToString() != string.Empty)
                writer.WriteElementString("httpQuery", httpQuery.ToString());

            writer.WriteFullEndElement();
        }

        #endregion
    }
}
